package org.texteasy;

import java.util.ArrayList;
import java.util.HashSet;

import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.provider.Contacts;
import android.provider.Contacts.Groups;
import android.provider.Contacts.People;
import android.provider.Contacts.People.Phones;

public class ContactsAccessorSdk3_4 extends ContactsAccessor {

	//Use type as the unique phone number id as only one number per cotact (primary) will be show. 
	private String[] contactsProjection = new String[] {People._ID,People.NAME, People.TYPE,People.NUMBER, People.TYPE};
	private String[] groupsProjection = new String[]{Groups._ID, Groups.SYSTEM_ID, Groups.NAME};
	
	@Override
	public Cursor queryContacts(ContentResolver contentResolver, String filter, long selectedGroupId,
			ArrayList<Integer> phoneTypes) {
		
		if(filter == null || "".equals(filter.trim())){
			filter = "%";
		}else{
			filter = filter + "%";
		}
		
		StringBuilder whereClause = new StringBuilder(People.NUMBER).
		append(" is not null and ").
		append(People.NAME).
		append(" like '").
		append(filter).
		append("'");
		
		filterPhoneTypes(phoneTypes, whereClause);
		
		if(selectedGroupId >=0){
			
			whereClause.append(" AND People.").
				append(People._ID).
				append(" in ").
				append("(SELECT person FROM groups, groupmembership WHERE ((groups._id=groupmembership.group_id OR " +
				"(groups._sync_account=groupmembership.group_sync_account AND groups._sync_id=groupmembership.group_sync_id))) " +
				"AND (GROUPS._ID = ").
				append(selectedGroupId).
				append("))");
		}
		
		return contentResolver.query(People.CONTENT_URI, contactsProjection, 
			whereClause.toString(), null, People.DEFAULT_SORT_ORDER);
	}

	private void filterPhoneTypes(ArrayList<Integer> phoneTypes, StringBuilder whereClause) {
		//get the phoneTypes to filter
		//There are a lot more Phone types than we show on the filter
		//The ones not shows are going to be associated with PhoneTypeOther
		//When making the query if PhoneTypeOther is selected then include
		//all PhoneTypes except those unselected in the Preferences (i.e.
		//if Other is selected and all the rest in prefs are unselected then
		//put in where clause: where Phone.Type not in (PhoneType.Mobile, PhoneType.Home...)
		//If Other and Mobile is selected and the rest are unselected then
		//where becomes: where Phone.Type not in (PhoneType.Home...))
		//If Other is not selected then where clause becomes a simple "in" affair where
		//all selected types are in the "in" statement
		//(i.e. where Phone.Type in (PhoneType.Mobile, PhoneType.Home...) )
		//If all types are selected then don't add anything to the where clause
		boolean[] selected = new boolean[]{false,false,false,false,false};
		for(int phoneType: phoneTypes){
			if(phoneType == Phones.TYPE_OTHER){
				selected[0] = true;
			}
			if(phoneType == Phones.TYPE_MOBILE){
				selected[1] = true;
			}
			if(phoneType == Phones.TYPE_CUSTOM){
				selected[2] = true;
			}
			if(phoneType == Phones.TYPE_HOME){
				selected[3] = true;
			}
			if(phoneType == Phones.TYPE_WORK){
				selected[4] = true;
			}
		}
		
		boolean allSelected = true;
		for(boolean selectedType: selected){
			if(!selectedType){
				allSelected = false;
			}
		}
		
		if(allSelected){
			//All are selected
		}else if(selected[0]){
			
			//Other is selected
			whereClause.append(" AND ").
				append(People.TYPE).
				append(" NOT IN (").
				append(buildInStatement(selected, true)).
				append(")");
		}else{
			//Other is not selected
			whereClause.append(" AND ").
			append(People.TYPE).
			append(" IN (").
			append(buildInStatement(selected, false)).
			append(")");
		}
	}

	private String buildInStatement(final boolean[] origSelected, 
		final boolean reverseSelections) {
		
		boolean[] selected = origSelected;
		if(reverseSelections){
			for(int i = 0; i < selected.length ;i++){
				selected[i] = !selected[i];
			}
		}
		
		StringBuilder toReturn = new StringBuilder();
		if(selected[1]){
			toReturn.append(Phones.TYPE_MOBILE).
				append(",");
		}
		
		if(selected[2]){
			toReturn.append(Phones.TYPE_CUSTOM).
				append(",");
		}
		
		if(selected[3]){
			toReturn.append(Phones.TYPE_HOME).
				append(",");
		}
		
		if(selected[4]){
			toReturn.append(Phones.TYPE_WORK).
				append(",");
		}
		
		if(toReturn.length() == 0){
			return "";
		}else{
			return toReturn.substring(0, toReturn.length() -1 );
		}
	}

	@Override
	public Cursor queryGroups(ContentResolver contentResolver) {
		return contentResolver.query(Groups.CONTENT_URI, 
			groupsProjection, null, null, Contacts.Groups.DEFAULT_SORT_ORDER);
	}

	
	@Override
	public Cursor queryContactsForPhoneNumbers(ContentResolver contentResolver,
			HashSet<Long> selectedIds) {
		
		StringBuffer buffer = new StringBuffer(" in(");
    	for(Long selectedId: selectedIds){
    		buffer.append(selectedId).
				append(","); 
    	}
		
    	String inStatement = buffer.substring(0, buffer.length() - 1) + ")";
		
		String[] projection = new String[] {People._ID,People.NUMBER, People.TYPE};
        
        Uri contacts = People.CONTENT_URI;
        
        return contentResolver.query(contacts, projection, 
    		"PEOPLE." + People._ID + inStatement, null, null);
	}
	
	@Override
	public String getPhoneColumnIndex() {
		return People.NUMBER;
	}
}
